<?php
/**
 * WorkOrder.php
 *
 * @copyright   2023 thingsworld.com.cn - All Rights Reserved
 * @link        http://thingsworld.com.cn/
 * @author      stiffer.chen <chenl@thingsworld.com.cn>
 * @created     2023-02-18 16:28:53
 * @modified    2023-02-18 16:28:53
 *
 */

namespace App\Models;

use App\Models\Dept\Zone;
use App\Models\WorkOrder\Audit;
use App\Models\WorkOrder\Callback;
use App\Models\WorkOrder\Image;
use App\Models\WorkOrder\Receipt;
use App\Models\WorkOrder\StatusHistory;
use App\Repositories\OperationLogRepo;
use App\Repositories\WorkOrderRepo;
use App\Services\DeptService;
use Carbon\Carbon;
use phpDocumentor\Reflection\Types\True_;

class WorkOrder extends BaseModel
{
    protected $table = 'work_order';
    protected $fillable = [
        'wo_number',
        'event_id',
        'customer_id',
        'type',
        'status',
        'service_type',
        'service_content',
        'plan_at',
        'description',
        'level',
        'contact_name',
        'contact_phone',
        'country_id',
        'country_code',
        'province_id',
        'province_code',
        'city_id',
        'city_code',
        'county_id',
        'county_code',
        'country_name',
        'province_name',
        'city_name',
        'county_name',
        'address',
        'create_user_id',
    ];

    protected $appends = [
        'create_time_format',
        'update_time_format',
        'logs',
        'status_stream',
        'audit_charge',
        'audit_manager',
        'audited',
        'timeout', // 是否已超时
        'callbacked',
        'show_close', // 关闭按钮是否显示
        'show_audit', // 审核按钮是否显示
        'show_callback', // 回访按钮是否显示
        'checked', // 是否有签到记录
        'is_create_person', // 是否为创建人
        'can_reassigned', // 是否可以转派
        'can_reassigned_apply' // 是否可以转派申请
    ];

    public function getTimeoutAttribute()
    {
        $planAt = $this->plan_at;
        $status = $this->status;
        $statuses = [
            WorkOrderRepo::STATUS_CREATED,
            WorkOrderRepo::STATUS_ASSIGNED,
            WorkOrderRepo::STATUS_ACCEPT,
        ];
        if ($planAt <= Carbon::now()->addDays(-3)->toDateString() . ' 00:00:00' && in_array($status, $statuses)) {
            return true;
        }
        return false;
    }

    public function getCanReassignedApplyAttribute()
    {
        // 已指派、已接受、已开始
        if (!in_array($this->status, [WorkOrderRepo::STATUS_ASSIGNED, WorkOrderRepo::STATUS_ACCEPT, WorkOrderRepo::STATUS_BEGIN])) {
            return false;
        }
        $userId = registry('user_id') ?? 0;
        $createUserId = $this->user_id; // 创建人
        $woUsers = $this->users;
        $woUserId = 0;
        foreach ($woUsers as $woUser) {
            if ($woUser->is_master) {
                $woUserId = $woUser->user_id;
            }
        }
        $userIds = [];
        if ($createUserId > 0) {
            $userIds[] = $createUserId;
        }
        if ($woUserId > 0) {
            $userIds[] = $woUserId;
        }
        if ($userId != 1 && !in_array($userId, $userIds)) {
            return false;
        }

        return true;
    }

    public function getCanReassignedAttribute()
    {
        $userId = registry('user_id') ?? 0;
        $provinceId = $this->province_id;
        $zone = Zone::byProvinceId($provinceId)->first();
        if (empty($zone)) {
            return false;
        }
        $dept = $zone->dept;
        $deptId = $dept->id;
        $leaders = (new DeptService())->getLeadersById($deptId);
        if (!$leaders->count()) {
            return false;
        }
        $leaderIds = $leaders->pluck('id')->toArray();
        if ($userId != 1 && !in_array($userId, $leaderIds)) {
            return false;
        }
        if (in_array($this->status, [WorkOrderRepo::STATUS_ASSIGNED, WorkOrderRepo::STATUS_ACCEPT, WorkOrderRepo::STATUS_BEGIN])) {
            return true;
        }
        return false;
    }

    public function getIsCreatePersonAttribute()
    {
        $userId = registry('user_id') ?? 0;
        if ($userId == 1) {
            return true;
        }
        if ($userId != $this->create_user_id) {
            return false;
        }
        return true;
    }

    public function getCheckedAttribute()
    {
        $workOrderId = $this->id;
        $checkinCount = \App\Models\CheckIn\WorkOrder::query()
            ->where('work_order_id', $workOrderId)
            ->count();
        return boolval($checkinCount);
    }

    public function getShowCloseAttribute()
    {
        return false;
        if ($this->status == WorkOrderRepo::STATUS_CLOSED) {
            return false;
        }
        return true;
    }

    /**
     * 见贴图: http://pm.thingsworld.com.cn/index.php?m=bug&f=view&bugID=27
     * 未审核: 主管可审核
     * 一级审核: 经理可审核
     * 二级审核: 不可审核
     */
    public function getShowAuditAttribute()
    {
        $userId = registry('user_id');
        $isManager = is_manager($userId);
        $isCharge = is_charge($userId);

        $workOrderId = $this->id;
        $auditChargeCount = Audit::query()
            ->where('work_order_id', $workOrderId)
            ->where('target', WorkOrderRepo::AUDIT_CHARGE)
            ->count();

        $auditManagerCount = Audit::query()
            ->where('work_order_id', $workOrderId)
            ->where('target', WorkOrderRepo::AUDIT_MANAGER)
            ->count();
        if ($isManager) {
            // 有记录: true, 没记录: false
            if ($auditManagerCount) {
                return false;
            }
            return true;
        } elseif ($isCharge) {
            // 有记录: true, 没记录: false
            if ($auditChargeCount) {
                return false;
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * 是否显示回访按钮
     * 二级审核未完成: 显示
     * 二级审核已完成
     *      已关闭: 不能回访
     *      未关闭: 可以回访
     */
    public function getShowCallbackAttribute()
    {
        if ($this->status == WorkOrderRepo::STATUS_CLOSED) {
            return false;
        }

        $auditHistory = Audit::query()
            ->where('work_order_id', $this->id)
            ->get()
            ->groupBy('target')
            ->toArray();
        $managerHistory = $auditHistory['manager'] ?? [];
        if (!$managerHistory) {
            return false;
        }
        $status = $this->status;
        if ($status == WorkOrderRepo::STATUS_CLOSED) {
            return false;
        }
        return true;
    }

    public function getCreateTimeFormatAttribute()
    {
        return Carbon::parse($this->create_time)->toDateTimeString();
    }

    public function getUpdateTimeFormatAttribute()
    {
        return Carbon::parse($this->update_time)->toDateTimeString();
    }

    public function getCallbackedAttribute()
    {
        $result = Callback::query()
            ->where('work_order_id', $this->id)
            ->count();
        return boolval($result);
    }

    public function getAuditChargeAttribute()
    {
        $workOrderId = $this->id;
        $auditChargeCount = Audit::query()
            ->where('work_order_id', $workOrderId)
            ->where('target', WorkOrderRepo::AUDIT_CHARGE)
            ->count();

        $auditManagerCount = Audit::query()
            ->where('work_order_id', $workOrderId)
            ->where('target', WorkOrderRepo::AUDIT_MANAGER)
            ->count();

        if (!$auditChargeCount && !$auditManagerCount) {
            return true;
        }
        return false;
    }

    public function getAuditManagerAttribute()
    {
        $workOrderId = $this->id;
        $auditChargeCount = Audit::query()
            ->where('work_order_id', $workOrderId)
            ->where('target', WorkOrderRepo::AUDIT_CHARGE)
            ->count();

        $auditManagerCount = Audit::query()
            ->where('work_order_id', $workOrderId)
            ->where('target', WorkOrderRepo::AUDIT_MANAGER)
            ->count();
        if ($auditChargeCount && !$auditManagerCount) {
            return true;
        }
        return false;
    }

    public function getAuditedAttribute()
    {
        $userId = registry('user_id');
        $isManager = is_manager($userId);
        $isCharge = is_charge($userId);

        $workOrderId = $this->id;
        $auditChargeCount = Audit::query()
            ->where('work_order_id', $workOrderId)
            ->where('target', WorkOrderRepo::AUDIT_CHARGE)
            ->count();

        $auditManagerCount = Audit::query()
            ->where('work_order_id', $workOrderId)
            ->where('target', WorkOrderRepo::AUDIT_MANAGER)
            ->count();
        if ($isManager) {
            // 有记录: true, 没记录: false
            if ($auditManagerCount) {
                return true;
            }
            return false;
        } elseif ($isCharge) {
            // 有记录: true, 没记录: false
            if ($auditChargeCount) {
                return true;
            }
            return false;
        } else {
            return false;
        }
    }

    public function getLogsAttribute()
    {
        $user = $this->users->where('is_master', 1)->toArray()[0] ?? [];
        $userId = $user['user_id'] ?? 0;
        $mobile = '';
        if ($userId) {
            $modelUser = UserModel::find($userId);
            if (!empty($modelUser)) {
                $mobile = $modelUser->mobile ?? '';
            }
        }
        $logs = OperationLog::byBusinessId($this->id)->byBusinessType(OperationLogRepo::BUSINESS_TYPE_WO)->orderBy('id')->get();
        if (empty($logs)) {
            return [];
        }

        $result = [];
        foreach ($logs as $log) {
            $temp = json_decode($log['business_body'], true);
            $temp['create_time'] = Carbon::parse($log['create_time'])->toDateTimeString();
            $temp['contact_phone'] = $mobile;
            $result[] = $temp;
        }
        return $result;
    }

    public function getStatusStreamAttribute()
    {
        $status = $this->status;
        $createdActive = $assignedActive = $acceptActive = $beginActive = $completeActive = 0;
        if ($status == WorkOrderRepo::STATUS_CREATED) {
            $createdActive = 1;
        }
        if ($status == WorkOrderRepo::STATUS_ASSIGNED) {
            $createdActive = 1;
            $assignedActive = 1;
        }
        if ($status == WorkOrderRepo::STATUS_ACCEPT) {
            $createdActive = 1;
            $assignedActive = 1;
            $acceptActive = 1;
        }
        if ($status == WorkOrderRepo::STATUS_BEGIN) {
            $createdActive = 1;
            $assignedActive = 1;
            $acceptActive = 1;
            $beginActive = 1;
        }
        if ($status == WorkOrderRepo::STATUS_COMPLETE) {
            $createdActive = 1;
            $assignedActive = 1;
            $acceptActive = 1;
            $beginActive = 1;
            $completeActive = 1;
        }
        $result = [
            ['status' => WorkOrderRepo::STATUS_CREATED, 'active' => $createdActive],
            ['status' => WorkOrderRepo::STATUS_ASSIGNED, 'active' => $assignedActive],
            ['status' => WorkOrderRepo::STATUS_ACCEPT, 'active' => $acceptActive],
            ['status' => WorkOrderRepo::STATUS_BEGIN, 'active' => $beginActive],
            ['status' => WorkOrderRepo::STATUS_COMPLETE, 'active' => $completeActive],
        ];
        return $result;
    }

    public function scopeByNumber($query, $number)
    {
        return $query->where('wo_number', $number);
    }

    public function scopeByEventId($query, $eventId)
    {
        return $query->where('event_id', $eventId);
    }

    public function images()
    {
        return $this->hasMany(Image::class);
    }

    public function products()
    {
        return $this->hasMany(\App\Models\WorkOrder\Product::class);
    }

    public function histories()
    {
        return $this->hasMany(StatusHistory::class);
    }

    public function users()
    {
        return $this->hasMany(\App\Models\WorkOrder\User::class);
    }

    public function create_user()
    {
        return $this->belongsTo(UserModel::class);
    }

    public function customer()
    {
        return $this->belongsTo(Customer::class);
    }

    public function receipt()
    {
        return $this->hasOne(Receipt::class, 'work_order_id', 'id');
    }

    public function audit()
    {
        return $this->hasMany(Audit::class);
    }

    public function dept_zone()
    {
        return $this->belongsTo(Zone::class, 'province_id', 'city_id');
    }

    public function callback()
    {
        return $this->hasOne(Callback::class);
    }

    public function receipts()
    {
        return $this->hasMany(Receipt::class);
    }

    public function question_feedback()
    {
        return $this->hasOne(QuestionFeedback::class, 'wo_id');
    }
}